﻿//  Copyright (c) Microsoft Corporation.  All Rights Reserved.
using System;
using System.Configuration;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Configuration;
using System.ServiceModel.Description;
using Sripirom.ATS.Core.Configuration;
using Sripirom.ATS.Core.Logging;
using Sripirom.ATS.Core.UnitOfWork;

namespace Sripirom.ATS.Core.ServiceModel.Activation
{                                            
    //This class is a custom derivative of ServiceHost
    //that can automatically enabled metadata generation
    //for any service it hosts.
    public class AtsDescribingServiceHost : ServiceHost
    {
        ILoggerFactory _loggerFactory;
        #region Constructor
        public AtsDescribingServiceHost(Type serviceType, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
            LoggerFactory.CreateLog().LogInfo("I: AtsDescribingServiceHost.Constructor Type " + serviceType.Name+". ");

           // InnitBusinessCommand(serviceType);
        }
        public AtsDescribingServiceHost(Type serviceType, IUnitOfWork uow, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
            

            LoggerFactory.CreateLog().LogInfo("I: AtsDescribingServiceHost.Constructor Type " + serviceType.Name + ". ");
      
        }

        #endregion                                                              
        
        //Overriding ApplyConfiguration() allows us to 
        //alter the ServiceDescription prior to opening
        //the service host. 
        protected override void ApplyConfiguration()
        {

           // ObjectFactory.

         
            //First, we call base.ApplyConfiguration()
            //to read any configuration that was provided for
            //the service we're hosting. After this call,
            //this.ServiceDescription describes the service
            //as it was configured.
            //base.ApplyConfiguration();

            // get the path to the configuration file, you can use this or any other path
            // you want.
            string configFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, String.Format("{0}.config", this.Description.Name));
                //Path.Combine(System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath,
            //                            String.Format("{0}.config", this.Description.Name));

            //If the file does not exist, then just use the base configuration which will read
            //from the web.config
            if (!System.IO.File.Exists(configFilePath))
            {
                base.ApplyConfiguration();
            }
            else
            {
                LoadConfigFromFile(configFilePath);
            }

            LoggerFactory.CreateLog().LogInfo("I: AtsDescribingServiceHost.ApplyConfiguration.");

            //Now that we've populated the ServiceDescription, we can reach into it
            //and do interesting things (in this case, we'll add an instance of
            //ServiceMetadataBehavior if it's not already there.
            ServiceMetadataBehavior mexBehavior = this.Description.Behaviors.Find<ServiceMetadataBehavior>();
            if (mexBehavior == null)
            {
                
                mexBehavior = new ServiceMetadataBehavior();
                this.Description.Behaviors.Add(mexBehavior);
                LoggerFactory.CreateLog().LogInfo("Add Behviors " + mexBehavior.GetType().Name);
            }
            else
            {
                LoggerFactory.CreateLog().LogInfo("Found Behviors " + mexBehavior.GetType().Name);
                //Metadata behavior has already been configured, 
                //so we don't have any work to do.
                return;
            }

            ////Add a metadata endpoint at each base address
            ////using the "/mex" addressing convention
            foreach (Uri baseAddress in this.BaseAddresses)
            {
                if (baseAddress.Scheme == Uri.UriSchemeHttp)
                {
                    LoggerFactory.CreateLog().LogInfo(String.Format("AddServiceEndpoint {0} {1}.", ServiceMetadataBehavior.MexContractName, "UriSchemeHttp"));
                    mexBehavior.HttpGetEnabled = true;
                    this.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName,
                                            MetadataExchangeBindings.CreateMexHttpBinding(),
                                            "mex");
                }
                else if (baseAddress.Scheme == Uri.UriSchemeHttps)
                {
                    LoggerFactory.CreateLog().LogInfo(String.Format("AddServiceEndpoint {0} {1}.", ServiceMetadataBehavior.MexContractName, "UriSchemeHttps"));
                    mexBehavior.HttpsGetEnabled = true;
                    this.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName,
                                            MetadataExchangeBindings.CreateMexHttpsBinding(),
                                            "mex");
                }
                else if (baseAddress.Scheme == Uri.UriSchemeNetPipe)
                {
                    LoggerFactory.CreateLog().LogInfo(String.Format("AddServiceEndpoint {0} {1}.", ServiceMetadataBehavior.MexContractName, "UriSchemeNetPipe"));
                    this.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName,
                                            MetadataExchangeBindings.CreateMexNamedPipeBinding(),
                                            "mex");
                }
                else if (baseAddress.Scheme == Uri.UriSchemeNetTcp)
                {
                    LoggerFactory.CreateLog().LogInfo(String.Format("AddServiceEndpoint {0} {1}.", ServiceMetadataBehavior.MexContractName, "UriSchemeNetTcp"));
                    this.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName,
                                            MetadataExchangeBindings.CreateMexTcpBinding(),
                                            "mex");
                }
            }

            
            LoggerFactory.CreateLog().LogInfo("O: AtsDescribingServiceHost.ApplyConfiguration.");
        }



        private void LoadConfigFromFile(string configFilePath)
        {
            var filemap = new System.Configuration.ExeConfigurationFileMap();
            filemap.ExeConfigFilename = configFilePath;

            var config = ConfigurationManager.OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None);

            var serviceModelSectionGroup = System.ServiceModel.Configuration.ServiceModelSectionGroup.GetSectionGroup(config);

            bool foundMatchingConfigElement = false;
            foreach (ServiceElement se in serviceModelSectionGroup.Services.Services)
            {
                if (se.Name == this.Description.ConfigurationName)
                {
                    base.LoadConfigurationSection(se);
                    foundMatchingConfigElement = true;
                    break;
                }
            }
            if (!foundMatchingConfigElement)
                throw new FileNotFoundException("Matching Service Element Configuration does not exist.");
        }
        
    }
}
